package handlers

import (
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"sysu-giep/internal/api/middleware"
	"sysu-giep/internal/database/models"
	"sysu-giep/internal/export"
	"sysu-giep/internal/service"
	"sysu-giep/internal/util"
	"sysu-giep/pkg/logger"
	"sysu-giep/pkg/response"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

var adminService *service.AdminService

// InitAdminHandlers 初始化管理员处理器
func InitAdminHandlers(as *service.AdminService) {
	adminService = as
}

// AdminGetUsers 管理员获取用户列表
// @Summary 管理员获取用户列表
// @Description 管理员获取用户列表，支持分页和筛选
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码" default(1)
// @Param size query int false "每页大小" default(10)
// @Param role query string false "角色"
// @Param status query string false "状态"
// @Success 200 {object} response.PageResponse{data=[]models.User}
// @Router /admin/users [get]
func AdminGetUsers(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
	role := c.Query("role")
	status := c.Query("status")

	// 参数验证
	if page < 1 {
		page = 1
	}
	if size < 1 || size > 100 {
		size = 10
	}

	users, total, err := adminService.GetUsers(page, size, role, status)
	if err != nil {
		logger.ErrorLog("获取用户列表失败", zap.Error(err))
		response.InternalServerError(c, "获取用户列表失败: "+err.Error())
		return
	}

	response.PageSuccess(c, users, total, page, size)
}

// AdminUpdateUserStatus 管理员更新用户状态
// @Summary 管理员更新用户状态
// @Description 管理员更新用户审核状态
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "用户ID"
// @Param request body UpdateUserStatusRequest true "状态信息"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /admin/users/{id}/status [put]
func AdminUpdateUserStatus(c *gin.Context) {
	_ = middleware.GetCurrentUserID(c) // 管理员ID，用于权限验证
	idStr := c.Param("id")

	var req models.UpdateUserStatusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	userID, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的用户ID")
		return
	}

	if err := adminService.UpdateUserStatus(uint(userID), req.Status); err != nil {
		logger.ErrorLog("更新用户状态失败", zap.Error(err))
		response.InternalServerError(c, "更新用户状态失败: "+err.Error())
		return
	}

	response.SuccessWithMessage(c, "用户状态更新成功", nil)
}

// AdminGetProjects 管理员获取课题列表
// @Summary 管理员获取课题列表
// @Description 管理员获取课题列表，支持分页和筛选
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码" default(1)
// @Param size query int false "每页大小" default(10)
// @Param status query string false "状态"
// @Success 200 {object} response.PageResponse{data=[]models.Project}
// @Router /admin/projects [get]
func AdminGetProjects(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
	status := c.Query("status")

	// 参数验证
	if page < 1 {
		page = 1
	}
	if size < 1 || size > 100 {
		size = 10
	}

	projects, total, err := adminService.GetProjects(page, size, status)
	if err != nil {
		logger.ErrorLog("获取课题列表失败", zap.Error(err))
		response.InternalServerError(c, "获取课题列表失败: "+err.Error())
		return
	}

	response.PageSuccess(c, projects, total, page, size)
}

// AdminUpdateProjectStatus 管理员更新课题状态
// @Summary 管理员更新课题状态
// @Description 管理员更新课题状态
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "课题ID"
// @Param request body UpdateProjectStatusRequest true "状态信息"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /admin/projects/{id}/status [put]
func AdminUpdateProjectStatus(c *gin.Context) {
	_ = middleware.GetCurrentUserID(c) // 管理员ID，用于权限验证
	idStr := c.Param("id")

	var req models.UpdateProjectStatusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	projectID, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的课题ID")
		return
	}

	if err := adminService.UpdateProjectStatus(uint(projectID), req.Status); err != nil {
		logger.ErrorLog("更新课题状态失败", zap.Error(err))
		response.InternalServerError(c, "更新课题状态失败: "+err.Error())
		return
	}

	response.SuccessWithMessage(c, "课题状态更新成功", nil)
}

// AdminGetApplications 管理员获取申请列表
// @Summary 管理员获取申请列表
// @Description 管理员获取申请列表，支持分页和筛选
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码" default(1)
// @Param size query int false "每页大小" default(10)
// @Param status query string false "状态"
// @Success 200 {object} response.PageResponse{data=[]models.Application}
// @Router /admin/applications [get]
func AdminGetApplications(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
	status := c.Query("status")

	// 参数验证
	if page < 1 {
		page = 1
	}
	if size < 1 || size > 100 {
		size = 10
	}

	applications, total, err := adminService.GetApplications(page, size, status)
	if err != nil {
		logger.ErrorLog("获取申请列表失败", zap.Error(err))
		response.InternalServerError(c, "获取申请列表失败: "+err.Error())
		return
	}

	response.PageSuccess(c, applications, total, page, size)
}

// AdminUpdateApplicationStatus 管理员更新申请状态
// @Summary 管理员更新申请状态
// @Description 管理员更新申请状态
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "申请ID"
// @Param request body UpdateApplicationStatusRequest true "状态信息"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /admin/applications/{id}/status [put]
func AdminUpdateApplicationStatus(c *gin.Context) {
	_ = middleware.GetCurrentUserID(c) // 管理员ID，用于权限验证
	idStr := c.Param("id")

	var req models.AdminUpdateApplicationStatusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	applicationID, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的申请ID")
		return
	}

	if err := adminService.UpdateApplicationStatus(uint(applicationID), req.Status, req.Feedback); err != nil {
		logger.ErrorLog("更新申请状态失败", zap.Error(err))
		response.InternalServerError(c, "更新申请状态失败: "+err.Error())
		return
	}

	response.SuccessWithMessage(c, "申请状态更新成功", nil)
}

// AdminGetStatistics 管理员获取统计信息
// @Summary 管理员获取统计信息
// @Description 管理员获取平台统计信息
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} response.Response{data=map[string]interface{}}
// @Router /admin/statistics [get]
func AdminGetStatistics(c *gin.Context) {

	statistics, err := adminService.GetStatistics()
	if err != nil {
		logger.ErrorLog("获取统计信息失败", zap.Error(err))
		response.InternalServerError(c, "获取统计信息失败: "+err.Error())
		return
	}

	response.Success(c, statistics)
}

// AdminExportStatistics 管理员导出统计报表
// @Summary 管理员导出统计报表
// @Description 管理员导出统计报表
// @Tags 管理员
// @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet // Excel
// @Produce text/csv // CSV
// @Produce application/pdf // PDF
// @Produce json // test
// @Security BearerAuth
// @Param format query string false "导出格式" default(excel)
// @Success 200 {object} response.Response
// @Router /admin/statistics/export [get]
func AdminExportStatistics(c *gin.Context) {
	format := c.DefaultQuery("format", "excel")
	//testMode := c.DefaultQuery("test", "false") == "true"

	// 限制支持的导出格式
	supportedFormats := []string{"excel", "csv", "pdf"}
	if !util.ContainsString(supportedFormats, format) {
		response.BadRequest(c, "不支持的导出格式，支持的格式："+strings.Join(supportedFormats, ","))
		return
	}

	// 从数据库查询需要导出的统计数据
	stats, err := adminService.GetStatistics()
	if err != nil {
		logger.ErrorLog("管理员获取统计数据失败", zap.Error(err))
		response.InternalServerError(c, "管理员获取数据失败")
		return
	}

	util.CleanAllNullChars(stats)

	var fileContent []byte
	var filename string

	switch format {
	case "excel":
		fileContent, filename, err = export.GenerateExcel(stats)
	case "csv":
		fileContent, filename, err = export.GenerateCSV(stats)
	case "pdf":
		fileContent, filename, err = export.GeneratePDF(stats)
	}

	if err != nil {
		logger.ErrorLog("管理员导出统计报表失败", zap.Error(err))
		response.InternalServerError(c, "管理员导出统计报表失败")
		return
	}

	// 测试模式：返回原始数据和文件信息（不触发下载）
	//if testMode {
	//	response.Success(c, gin.H{
	//		"message":    "测试模式：导出数据如下",
	//		"format":     format,
	//		"filename":   filename,
	//		"file_size":  len(fileContent), // 文件大小（字节）
	//		"stats_data": stats,            // 原始统计数据（用于验证）
	//	})
	//	return
	//}

	// 设置响应头，触发浏览器下载
	encodedFileName := url.QueryEscape(filename) // 处理中文文件名
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename*=UTF-8''%s", encodedFileName))
	c.Header("Content-Type", util.GetMimeType(format)) // 设置正确的MIME类型
	c.Header("Content-Length", fmt.Sprintf("%d", len(fileContent)))

	// 返回文件内容
	c.Data(http.StatusOK, util.GetMimeType(format), fileContent)
}

// AdminManualMatch 管理员手动匹配
// @Summary 管理员手动匹配
// @Description 管理员手动将学生或导师匹配到企业课题
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body models.AdminManualMatchRequest true "匹配信息"
// @Success 200 {object} response.Response{data=models.AdminManualMatchResponse}
// @Failure 400 {object} response.Response
// @Router /admin/matches [post]
func AdminManualMatch(c *gin.Context) {
	_ = middleware.GetCurrentUserID(c) // 管理员ID，用于权限验证

	var req models.AdminManualMatchRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	result, err := adminService.ManualMatch(req)
	if err != nil {
		logger.ErrorLog("手动匹配失败", zap.Error(err))
		response.BadRequest(c, "匹配失败: "+err.Error())
		return
	}

	response.SuccessWithMessage(c, "匹配成功", result)
}

// AdminGetMatchCandidates 获取课题的匹配候选者
// @Summary 获取课题的匹配候选者
// @Description 获取可以匹配到指定课题的学生或导师列表
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param project_id query int true "课题ID"
// @Param role query string true "用户角色" Enums(student, tutor)
// @Success 200 {object} response.Response{data=[]models.User}
// @Router /admin/matches/candidates [get]
func AdminGetMatchCandidates(c *gin.Context) {
	projectIDStr := c.Query("project_id")
	role := c.Query("role")

	if projectIDStr == "" || role == "" {
		response.BadRequest(c, "课题ID和用户角色不能为空")
		return
	}

	projectID, err := strconv.ParseUint(projectIDStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的课题ID")
		return
	}

	// 验证角色
	if role != string(models.RoleStudent) && role != string(models.RoleTutor) {
		response.BadRequest(c, "无效的用户角色，只能是student或tutor")
		return
	}

	candidates, err := adminService.GetMatchCandidates(uint(projectID), role)
	if err != nil {
		logger.ErrorLog("获取匹配候选者失败", zap.Error(err))
		response.InternalServerError(c, "获取匹配候选者失败: "+err.Error())
		return
	}

	response.Success(c, candidates)
}

// AdminGetProjectCandidates 获取用户的课题候选者
// @Summary 获取用户的课题候选者
// @Description 获取可以匹配给指定用户的课题列表
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param user_id query int true "用户ID"
// @Success 200 {object} response.Response{data=[]models.Project}
// @Router /admin/matches/project-candidates [get]
func AdminGetProjectCandidates(c *gin.Context) {
	userIDStr := c.Query("user_id")

	if userIDStr == "" {
		response.BadRequest(c, "用户ID不能为空")
		return
	}

	userID, err := strconv.ParseUint(userIDStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的用户ID")
		return
	}

	candidates, err := adminService.GetProjectCandidates(uint(userID))
	if err != nil {
		logger.ErrorLog("获取课题候选者失败", zap.Error(err))
		response.InternalServerError(c, "获取课题候选者失败: "+err.Error())
		return
	}

	response.Success(c, candidates)
}

// AdminRemoveMatch 移除匹配
// @Summary 移除匹配
// @Description 管理员移除已存在的匹配
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "匹配ID"
// @Success 200 {object} response.Response
// @Router /admin/matches/{id} [delete]
func AdminRemoveMatch(c *gin.Context) {
	_ = middleware.GetCurrentUserID(c) // 管理员ID，用于权限验证
	matchIDStr := c.Param("id")

	matchID, err := strconv.ParseUint(matchIDStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的匹配ID")
		return
	}

	if err := adminService.RemoveMatch(uint(matchID)); err != nil {
		logger.ErrorLog("移除匹配失败", zap.Error(err))
		response.BadRequest(c, "移除匹配失败: "+err.Error())
		return
	}

	response.SuccessWithMessage(c, "匹配已移除", nil)
}

// AdminGetMatches 获取所有匹配记录
// @Summary 获取所有匹配记录
// @Description 管理员获取所有匹配记录，支持分页
// @Tags 管理员
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码" default(1)
// @Param size query int false "每页大小" default(10)
// @Success 200 {object} response.PageResponse{data=[]models.ProjectMatch}
// @Router /admin/matches [get]
func AdminGetMatches(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))

	// 参数验证
	if page < 1 {
		page = 1
	}
	if size < 1 || size > 100 {
		size = 10
	}

	matches, total, err := adminService.GetMatches(page, size)
	if err != nil {
		logger.ErrorLog("获取匹配记录失败", zap.Error(err))
		response.InternalServerError(c, "获取匹配记录失败: "+err.Error())
		return
	}

	response.PageSuccess(c, matches, total, page, size)
}
